package nl.ViewerServer.ServerManager.UserManager;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentHashMap;

import nl.ViewerServer.Database.UserDatabaseConnection;
import nl.ViewerServer.ServerManager.UserManager.Objects.User;

import org.apache.log4j.Logger;

/**
 * The UserManager is responsible for all information regarding users, groups, ACLs, privileges, etc.
 * 
 * @author Jeroen Verschuur
 * 
 */
public class UserManager {
   private static Logger                   log       = Logger.getLogger( UserManager.class );
   private ConcurrentHashMap<String, User> userCache = new ConcurrentHashMap<String, User>();
   private UserDatabaseConnection          database  = null;

   /**
    * The UserManager object is responsible for retrieving all users/groups/etc from the database. This manager will
    * create it's own database object to prevent locking of the database connection (as this manager does many db
    * calls!)
    * 
    * @throws ClassNotFoundException,
    *            SQLException when the database connection for this manager cannot be initialized
    */
   public UserManager() throws ClassNotFoundException, SQLException {
      // our own private database connection
      database = new UserDatabaseConnection();
   }

   /**
    * Return a User object containing all usable information for the specified user. In case caching is implemented by
    * this manager, the purgeCache parameter will specify when a fresh retrieval is necessary.
    * 
    * @param username
    * @param password
    * @param purgeCache
    * @return
    * @throws SQLException
    */
   public User getUser( String username, String password, boolean purgeCache ) throws SQLException {
      // TODO: we could implement some sort of time-based caching in which the user- and group objects are cached for a
      // certain time before re-fetching them from the database
      User u = database.getUser( username );
      if( !u.password.equals( password ) )
         return null;

      return u;
   }

   /**
    * This method will check the if the given group has the given privilege on the provided ACL.
    * 
    * @param groupId
    * @param privilege
    * @return
    */
   public boolean groupHasPrivilege( String acl, String privilege, int groupId ) throws SQLException {
      if( acl == null || privilege == null )
         return true;

      // TODO: caching?
      return database.groupHasPrivilege( acl, privilege, groupId );
   }

   /**
    * This method will verify whether a given user may use the provided privilege on the provided ACL, by verifing
    * whether any of the groups the user belongs to has that privilege.
    * 
    * @param acl
    * @param privilege
    * @param userId
    * @return
    * @throws SQLException
    */
   public boolean userHasPrivilege( String acl, String privilege, User user ) throws SQLException {
      if( acl == null || privilege == null )
         return true;

      ArrayList<Integer> userGroupIds = database.getUserGroupIds( user );

      if( userGroupIds == null )
         return false;

      // go through all possible groups for this user
      for( Integer g : userGroupIds )
         // check whether that group has the privilege
         if( groupHasPrivilege( acl, privilege, g ) )
            return true;

      return false;
   }

   public void removeUserCache( String username ) {
      userCache.remove( username );
      log.debug( "Removed cache entry for user " + username );
   }

}
